package com.husd.framework.a_autocode_new.splitword;

import com.husd.framework.a_autocode_new.scanner.CharScanner;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 可以作为一个公共的分词器 子类只需要指定需要按哪些字符分词即可
 * 一般来说 都是 空格 回车 换行 单引号 双引号
 *
 * @author shengdonghu@126.com
 * @date 2024/1/19 15:46
 */
public abstract class AbstractSplitWord {

    protected CharScanner charScanner;

    public AbstractSplitWord(String str) {
        this.str = str;
        charScanner = new CharScanner(this.str);
        char[] charArray = splitChar();
        for (Character c : charArray) {
            splitCharSet.add(new Character(c));
        }
    }

    protected String str;
    StringBuilder sb = new StringBuilder();
    List<String> res = new ArrayList<>();
    Set<Character> splitCharSet = new HashSet<>();

    /**
     * 这个是指定分词器的分词符号
     *
     * @return
     */
    protected abstract char[] splitChar();

    protected abstract char[] ignoreChar();

    public List<String> split() {

        if (StringUtils.isBlank(this.str)) {
            return new ArrayList<>();
        }
        OUT:
        // 考虑换行是不是要忽略？shi
        while (charScanner.haveC()) {
            Character c = charScanner.current();
            // 单引号和双引号是特殊字符 需要特殊处理
            if (c == '\'') {
                add2Res(c);
                pushOriginContent('\'');
                add2Res(c);
                continue OUT;
            } else if (c == '\"') {
                add2Res(c);
                pushOriginContent('\"');
                add2Res(c);
                continue OUT;
            }
            boolean splitOrNot = splitCharSet.contains(c);
            if (splitOrNot) {
                // 这个是记录之前的元素
                add2Res();
                // 空格 \n \t 都不记录
                boolean ignore = isIgnoreChar(c);
                if (!ignore) {
                    add2Res(c);
                }
            } else {
                sb.append(c);
            }
            charScanner.next();
        }
        return res;
    }

    private boolean isIgnoreChar(Character c) {

        char[] arr = ignoreChar();
        for (char item : arr) {
            if (c == item) {
                return true;
            }
        }
        return false;
    }

    private void pushOriginContent(char c) {
        add2Res(); // 把之前的结束
        // 移动指针 不过要考虑移动完指针之后 后面就没有数据了
        Character next = null;
        int originLen = 0;
        while (charScanner.next() && charScanner.current() != c) {
            next = charScanner.current();
            sb.append(next);
            originLen++;
        }
        // 为了预防单引号或者双引号没有闭合
        // '' 这种没有数据的 需要单独处理一下
        if (originLen == 0) {
            // 说明是 '' "" 这种空串
        }
        addEmpty2Res();
        charScanner.next();
    }

    private void add2Res() {
        if (this.sb.length() > 0) {
            this.res.add(this.sb.toString());
            this.sb.setLength(0);
        }
    }

    private void add2Res(char c) {
        this.res.add(String.valueOf(c));
    }

    private void addEmpty2Res() {
        if (this.sb.length() <= 0) {
            this.res.add("");
            this.sb.setLength(0);
        } else {
            this.res.add(this.sb.toString());
            this.sb.setLength(0);
        }
    }
}
